#include "Cmaid_Gtest.h"

Cmaid_Gtest_Constructor_Param cmaid_gtest_string_params[] = {
	{&cmaid_value_const_string, true},
	{&cmaid_value_inline_string, false},
	{&cmaid_gtest_dup_string, false}
};
Cmaid_Gtest_Constructor_Param *cmaid_gtest_string_param_first =
		&cmaid_gtest_string_params[0];
Cmaid_Gtest_Constructor_Param *cmaid_gtest_string_param_last =
		&cmaid_gtest_string_params[sizeof(cmaid_gtest_string_params)/sizeof(Cmaid_Gtest_Constructor_Param)];

static const char *cmaid_gtest_names_data[] =
{
	"Dirac",
	"Schroedinger",
	"Heisenberg",
	"Einstein",
	"Bethe",
	"Born",
	"Bohr",
	"Pauli",
	"Fermi",
	"Planck",
	"Feynman",
	"Wigner",
	"de Broglie",
	"Jordan",
	"Klein",
	"Gordon",
	"Franck",
	"Hertz",
	"Brillouin",
	"Seitz",
	"Landau",
	"Lenard",
	"von Weizsaecker",
	"Tscherenkow",
	"Carnot",
	"Edison",
	"Bravais",
	"Zeeman",
	"Abrikossow",
	"Ochsenfeld",
	"Rydberg",
	"Hall",
	"Ampere",
	"Schottky",
	"Roentgen",
	"Biot",
	"Rutherford",
	"Larmor",
	"Fourier",
	"Kelvin",
	"Tesla",
	"Green",
	"Geiger",
	"Bloch",
	"von Laue",
	"Mott",
	"Pascal",
	"Ohm",
	"Laplace",
	"Compton",
	"Fresnel",
	"Thomson",
	"Debye",
	"Kirchhoff",
	"Kepler",
	"Hamilton",
	"Millikan",
	"Drude",
	"Volta",
	"Bragg",
	"Kittel",
	"Gruenberg",
	"Bose",
	"Poisson",
	"Moessbauer",
	"Newton",
	"Stark",
	"Hahn",
	"Gibbs",
	"Gay-Lussac",
	"Seebeck",
	"Galilei",
	"Joule",
	"Leibniz",
	"Celsius",
	"Arrhenius",
	"Boltzmann",
	"Curie",
	"Young",
	"Sommerfeld",
	"Doppler",
	"Ewald"
};

static const char *cmaid_gtest_first_names_data[] =
{
	"Paul",
	"Erwin",
	"Werner",
	"Albert",
	"Hans",
	"Max",
	"Niels",
	"Wolfgang",
	"Enrico",
	"Max",
	"Richard",
	"Eugene Paul",
	"Louis-Victor",
	"Pascual",
	"Oskar",
	"Walter",
	"James",
	"Gustav Ludwig",
	"Leon",
	"Frederick",
	"Lew Dawidowitsch",
	"Philipp",
	"Carl Friedrich",
	"Pawel",
	"Nicolas",
	"Thomas Alva",
	"Auguste",
	"Pieter",
	"Alexei Alexejewitsch",
	"Robert",
	"Johannes Robert",
	"John L.",
	"Andre Marie",
	"Walter",
	"Wilhelm Conrad",
	"Jean-Baptiste",
	"Ernest",
	"Joseph",
	"Jean Baptiste Joseph",
	"Lord",
	"Nikola",
	"George",
	"Hans",
	"Felix",
	"Max",
	"Nevill Francis",
	"Blaise",
	"George Simon",
	"Pierre-Simon",
	"Arthur Holly",
	"Augustin Jean",
	"George Paget",
	"Petrus Josephus",
	"Gustav Robert",
	"Johannes",
	"Wiliam R.",
	"Robert Andrew",
	"Paul",
	"Alessandro",
	"William",
	"Charles",
	"Peter",
	"Satyendranath",
	"Simeon Denis",
	"Rudolf",
	"Isaac",
	"Johannes",
	"Otto",
	"Josiah Willard",
	"Joseph Louis",
	"Thomas Johann",
	"Galileo",
	"James Prescott",
	"Gottfried Wilhelm",
	"Anders",
	"Svante",
	"Ludwig",
	"Marie",
	"Thomas",
	"Arnold",
	"Andreas Christian",
	"Paul Peter"
};

static const int CMAID_GTEST_NAMES_COUNT 
		= sizeof(cmaid_gtest_names)/sizeof(const char*);

static int
cmaid_gtest_cstring_compare(const void *data1, const void *data2)
{
	const char *string1 = (const char *)data1;
	const char *string2 = (const char *)data2;

	return strcmp(string1, string2);
}

static int
cmaid_gtest_cstring_compare_alt(const void *data1, const void *data2)
{
	const char *string1 = (const char *)data1;
	const char *string2 = (const char *)data2;

	return strcmp(string1, string2) * -1;
}

static std::string
cmaid_gtest_cstring_to_string(const void *data)
{
	const char *s = (const char *)data;
	return std::string(s);
}

static void *
cmaid_gtest_cstring_data_get(void *data, size_t i)
{
	void **array = (void **)data;
	return array[i];
}

const Cmaid_Gtest_Data cmaid_gtest_names = {
	(void **)cmaid_gtest_names_data,
	CMAID_GTEST_NAMES_COUNT,
	cmaid_gtest_cstring_compare,
	cmaid_gtest_cstring_compare_alt,
	cmaid_gtest_cstring_to_string,
	cmaid_gtest_cstring_data_get
};

const Cmaid_Gtest_Data cmaid_gtest_first_names = {
	(void **)cmaid_gtest_first_names_data,
	CMAID_GTEST_NAMES_COUNT,
	cmaid_gtest_cstring_compare,
	cmaid_gtest_cstring_compare_alt,
	cmaid_gtest_cstring_to_string,
	cmaid_gtest_cstring_data_get
};

const Cmaid_Value cmaid_gtest_dup_string = {
	cmaid_value_string_compare, cmaid_value_string_hash, 0, 
	{NULL, NULL, NULL},
	{cmaid_value_string_dup, cmaid_value_string_free}
};

/* integer data */
Cmaid_Gtest_Constructor_Param cmaid_gtest_integer_param = {
	&cmaid_gtest_inline_integer, false
};

static int cmaid_gtest_numbers_data[] = {
	110,	290,	11,	69,	209,	468,	17,	293,
	164,	350,	115,	322,	361,	2,	446,	281,
	400,	375,	153,	116,	143,	329,	420,	133,
	363,	192,	27,	275,	104,	213,	352,	427,
	273,	288,	396,	114,	341,	413,	201,	280,
	66,	227,	406,	79,	259,	176,	106,	0,
	328,	270,	449,	165,	163,	43,	391,	202,
	49,	105,	149,	318,	387,	389,	141,	408,
	486,	354,	8,	33,	421,	385,	25,	485,
	196,	31,	82,	434,	423,	358,	255,	287,
	23,	122,	489,	19,	126,	44,	120,	131,
	332,	448,	238,	264,	454,	218,	157,	436,
	225,	437,	443,	179,	265,	475,	180,	487,
	339,	492,	395,	491,	223,	113,	92,	48,
	61,	506,	190,	67,	484,	439,	355,	243,
	503,	159,	74,	337,	151,	458,	480,	334,
	419,	309,	301,	125,	407,	496,	187,	50,
	368,	283,	244,	170,	118,	457,	181,	479,
	401,	494,	99,	236,	240,	147,	233,	172,
	266,	32,	210,	161,	156,	178,	221,	78,
	85,	135,	504,	356,	397,	450,	276,	41,
	414,	14,	22,	29,	34,	498,	250,	36,
	320,	268,	195,	382,	441,	235,	346,	476,
	217,	335,	121,	94,	278,	272,	207,	463,
	150,	432,	410,	208,	70,	84,	186,	6,
	500,	9,	60,	175,	430,	128,	129,	465,
	459,	289,	261,	26,	461,	279,	245,	478,
	403,	45,	359,	327,	393,	373,	304,	83,
	160,	198,	103,	367,	76,	73,	502,	291,
	215,	219,	119,	456,	197,	477,	222,	174,
	451,	214,	112,	464,	511,	47,	347,	111,
	148,	308,	340,	100,	130,	323,	312,	292,
	35,	507,	58,	353,	452,	91,	319,	330,
	473,	488,	134,	315,	253,	374,	384,	95,
	370,	13,	183,	136,	313,	307,	239,	258,
	405,	56,	228,	455,	317,	497,	102,	117,
	68,	234,	51,	107,	349,	348,	416,	88,
	89,	366,	109,	189,	333,	3,	394,	267,
	269,	246,	152,	173,	438,	24,	15,	390,
	284,	360,	371,	81,	65,	299,	132,	98,
	303,	139,	453,	402,	20,	54,	499,	260,
	285,	381,	357,	248,	362,	62,	203,	411,
	444,	388,	10,	342,	229,	481,	369,	378,
	38,	505,	415,	466,	404,	90,	101,	169,
	435,	296,	282,	63,	52,	40,	231,	302,
	18,	383,	194,	351,	254,	431,	199,	80,
	300,	140,	324,	286,	188,	386,	344,	166,
	4,	226,	510,	158,	447,	86,	398,	108,
	230,	310,	495,	171,	380,	249,	433,	16,
	470,	277,	21,	372,	252,	424,	144,	377,
	59,	46,	55,	429,	474,	321,	399,	471,
	237,	442,	97,	220,	445,	326,	37,	336,
	343,	412,	409,	460,	57,	168,	295,	247,
	482,	425,	256,	96,	53,	469,	162,	493,
	294,	177,	212,	30,	5,	193,	483,	124,
	87,	64,	490,	501,	422,	191,	75,	325,
	1,	182,	509,	364,	42,	39,	376,	467,
	426,	205,	365,	137,	297,	462,	241,	123,
	206,	440,	216,	146,	142,	72,	379,	472,
	305,	271,	298,	232,	242,	184,	138,	154,
	508,	71,	211,	274,	263,	311,	428,	331,
	7,	345,	185,	338,	251,	417,	12,	93,
	204,	257,	418,	314,	224,	155,	167,	392,
	145,	77,	127,	306,	200,	28,	316,	262
};

static const int CMAID_GTEST_NUMBERS_COUNT 
		= sizeof(cmaid_gtest_numbers_data)/sizeof(int);

static int
cmaid_gtest_integer_compare(const void *data1, const void *data2)
{
	int i1 = *((const int *)data1);
	int i2 = *((const int *)data2);

	if (i1 < i2)
		return -1;
	else if (i1 > i2)
		return 1;

	return 0;
}

static int
cmaid_gtest_integer_compare_alt(const void *data1, const void *data2)
{
	int i1 = *((const int *)data1);
	int i2 = *((const int *)data2);

	if (i1 > i2)
		return -1;
	else if (i1 < i2)
		return 1;

	return 0;
}

static unsigned int
cmaid_gtest_integer_hash(const void *v, unsigned int *size)
{
	*size = sizeof(int);
	return *((const int*)v);
}

static std::string
cmaid_gtest_integer_to_string(const void *data)
{
	std::ostringstream stream;
	int i = *((const int *)data);
	stream << i;
	return stream.str();
}

static void *
cmaid_gtest_integer_data_get(void *data, size_t i)
{
	int *array = (int *)data;
	return &array[i];
}

const Cmaid_Gtest_Data cmaid_gtest_numbers = {
	(void **)cmaid_gtest_numbers_data,
	CMAID_GTEST_NUMBERS_COUNT,
	cmaid_gtest_integer_compare,
	cmaid_gtest_integer_compare_alt,
	cmaid_gtest_integer_to_string,
	cmaid_gtest_integer_data_get
};

const Cmaid_Value cmaid_gtest_inline_integer = {
	cmaid_gtest_integer_compare, cmaid_gtest_integer_hash, sizeof(int),
	{NULL, NULL, NULL},
	{NULL, NULL}
};

/* pointers */
static const Cmaid_Value null_value_structure = {
	NULL, NULL, 0, {NULL, NULL, NULL}, {NULL, NULL}
};

Cmaid_Gtest_Constructor_Param cmaid_gtest_pointer_params[] = {
	{NULL, true},
	{&null_value_structure, true},
	{&cmaid_value_pointer, true},
};

Cmaid_Gtest_Constructor_Param *cmaid_gtest_pointer_param_first =
		&cmaid_gtest_pointer_params[0];
Cmaid_Gtest_Constructor_Param *cmaid_gtest_pointer_param_last =
		&cmaid_gtest_pointer_params[sizeof(cmaid_gtest_pointer_params)/sizeof(Cmaid_Gtest_Constructor_Param)];

static std::string
cmaid_gtest_pointer_to_string(const void *data)
{
	std::ostringstream stream;
	stream << data;
	return stream.str();
}

static int
cmaid_gtest_pointer_compare_alt(const void *data1, const void *data2)
{
	return cmaid_value_pointer_compare(data1, data2) * -1;
}


static const Cmaid_Gtest_Data cmaid_gtest_pointers[] =
{
	{
		(void **)cmaid_gtest_numbers_data,
		CMAID_GTEST_NUMBERS_COUNT,
		cmaid_value_pointer_compare,
		cmaid_gtest_pointer_compare_alt,
		cmaid_gtest_pointer_to_string,
		cmaid_gtest_integer_data_get
	},
	{
		(void **)cmaid_gtest_names_data,
		CMAID_GTEST_NAMES_COUNT,
		cmaid_value_pointer_compare,
		cmaid_gtest_pointer_compare_alt,
		cmaid_gtest_pointer_to_string,
		cmaid_gtest_cstring_data_get
	},
	{
		(void **)cmaid_gtest_first_names_data,
		CMAID_GTEST_NAMES_COUNT,
		cmaid_value_pointer_compare,
		cmaid_gtest_pointer_compare_alt,
		cmaid_gtest_pointer_to_string,
		cmaid_gtest_cstring_data_get
	}
};

const Cmaid_Gtest_Data *cmaid_gtest_pointers_first =
	&cmaid_gtest_pointers[0];
const Cmaid_Gtest_Data *cmaid_gtest_pointers_last =
	&cmaid_gtest_pointers[sizeof(cmaid_gtest_pointers)
				/sizeof(*cmaid_gtest_pointers)];
